﻿module;

#include <cstdint>
#include <cstdlib>
#include <print>
#include <chrono>
#include <iostream>
#include <ranges>
#include <mutex>
#include <memory>
#include <format>
#include <ctime>
#include <iomanip>

export module zzj.menu;

import zzj.col;

using namespace col;
using namespace col::literals;
using namespace std::literals;

namespace zzj
{
	inline namespace menu
	{
		
	}
}


export namespace menu
{
	using MsgTy = 
	enum class MessageType : std::int_fast8_t
	{
		NORMAL = 0,
		MESSAGE,
		SUCCESS,
		NOTE,
		WARNING,
		ERROR
	};

	/* 界面类 */
	class Menu
	{
	private:
		using TimePoint = std::chrono::high_resolution_clock::time_point;

		struct StatFlag
		{
			bool is_ready{ false };
			bool is_fresh{ false };
			bool is_wait{ false };
			bool is_readFile{ false };
			bool is_writeFile{ false };
			bool is_prnMsg{ false };
		} statFlag;

		std::string m_systemName{ "系统" };
		std::string m_userName{ "user" };

		int m_optionId{ 1 };
		int m_option{ 1 };


		TimePoint m_startTime{std::chrono::high_resolution_clock::now()};
		TimePoint m_latestTime{m_startTime};

	public:
		Menu() = default;
		explicit(false) Menu(std::string_view const sys_name)
			: m_systemName{ sys_name } {
		}
		explicit(false) Menu(std::string_view const sys_name , std::string_view const usr_name)
			: m_systemName{ sys_name }, m_userName{ usr_name } {
		}
		Menu(Menu&&) = default;
		~Menu() = default;
		Menu(Menu const&) = default;
		Menu& operator=(Menu const&) = default;
		Menu& operator=(Menu&&) = default;

		void printMsg(MsgTy const ty, std::string_view msg);

		void statusBar();
		void statusBarFr();
		void fresh();
		void waitEnterMsg();
		void options();
		void ready();
	};


	/*****************************************************************
	 *
	 *		MENU 定义
	 *
	 *****************************************************************/

	inline void Menu::printMsg(MsgTy const ty, std::string_view msg)
	{
		statFlag.is_prnMsg = true;

		std::string tyMsg;
		auto col = Color(ColorName::DEFAULT);
		switch (ty) {
		case MsgTy::MESSAGE:
			col.change(ColorName::CYAN);
			tyMsg = "MSG";
			break;
		case MessageType::SUCCESS:
			col.change(ColorName::GREEN);
			tyMsg = "SUCCESS";
			break;
		case MsgTy::NOTE:
			col.change(ColorName::YELLOW);
			tyMsg = "NOTE";
			break;
		case MsgTy::WARNING:
			col.change(ColorName::YELLOW);
			tyMsg = "WARNING";
			break;
		case MsgTy::ERROR:
			col.change(ColorName::RED);
			tyMsg = "ERROR";
			break;
		case MsgTy::NORMAL:
			col.change(ColorName::GREEN);
			tyMsg = "NORMAL";
			break;
		default:
			tyMsg = "NULL";
			col.change(ColorName::DEFAULT);
		}
		col.print();
		std::println("[{}][{}]:「{}」", ">", tyMsg, msg);
	}


	inline void Menu::statusBar()
	{
		auto const latestTime = std::chrono::high_resolution_clock::now();
		auto const dur = latestTime - m_latestTime;

		m_latestTime = latestTime;

		char timeStr[80]{};

		{
		    auto const now = std::chrono::system_clock::now();
		    std::time_t const now_c = std::chrono::system_clock::to_time_t(now);
		       std::tm now_tm;
		       localtime_s(&now_tm, &now_c);
		    std::strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:%M:%S", &now_tm);
		}

		auto col = Color(ColorName::CYAN);

		std::print("[{1:}][{0:}]", m_userName, m_systemName);
		col.changePrn(ColorName::GREEN);
		std::println("[{}][{}{}s]", 
			timeStr, "Times：", 
			std::chrono::duration_cast<std::chrono::seconds>(dur).count());

		if constexpr (false) {
			//std::println("[{:%Y-%m-%d %H:%M}][{}{}s]", 
			//	std::chrono::system_clock::now(), 
			//	"Times：", std::chrono::duration_cast<std::chrono::seconds>(dur).count());
		}

		col.changePrn(ColorName::MAGENTA);
		if (statFlag.is_readFile) {
			std::print("[文件读取成功]");
		} else {
			std::print("[未读取文件]");
		}
		if (statFlag.is_writeFile) {
			std::print("[文件写入成功]");
		} else {
			std::print("[未写入文件]");
		}
		col.changePrn(ColorName::RED);
		std::println("[End]\n");

		statFlag.is_fresh = false;
	}

	inline void Menu::statusBarFr()
	{
		if (!statFlag.is_fresh) {
			Menu::fresh();
			this->statusBar();
		}
		statFlag.is_fresh = false;
	}

	inline void Menu::fresh()
	{
		if constexpr (sys_info.is_windows) {
			std::system("cls");
		} else {
			std::system("clear");
		}
		statFlag.is_fresh = true;
	}


	inline void Menu::waitEnterMsg()
	{
		auto const markedWords{ "按下回车键以继续"s };

		statFlag.is_wait = true;
		{
			auto col = Color{ ColorName::YELLOW };
			this->printMsg(MessageType::NOTE, markedWords);
			std::cin.clear();
			if (std::cin.rdbuf()->in_avail() > 0) {
				std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
			}
			std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
		}
		statFlag.is_wait = false;
	}

	inline void Menu::options()
	{
		statFlag.is_fresh = false;

		std::vector<int> vv;

		for (auto val : std::ranges::istream_view<int>(std::cin)
			| std::views::take_while([](const auto& v) {return v < 5; })
			| std::views::transform([](const auto& v) {return v * 2; })) {
			std::println("> {}", val);
			vv.push_back(val);
		}
		std::println("end input");
	}

	inline void Menu::ready()
	{
		statFlag.is_ready = true;
		this->printMsg(MessageType::MESSAGE, "系统就绪！");
	}
}